package com.alawn.web.security.controller;

import java.util.ArrayList;
import java.util.List;

import javax.faces.event.AjaxBehaviorEvent;

import org.ocpsoft.rewrite.annotation.Join;
import org.primefaces.component.selectonebutton.SelectOneButton;
import org.primefaces.event.NodeSelectEvent;
import org.primefaces.model.DefaultTreeNode;
import org.primefaces.model.TreeNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import com.alawn.framework.core.web.faces.annotation.MessageRequired;
import com.alawn.framework.core.web.faces.annotation.MessageType;
import com.alawn.framework.core.web.faces.controller.FacesController;
import com.alawn.framework.services.enums.ResourceType;
import com.alawn.framework.services.security.Resource;
import com.alawn.framework.services.system.Dictionary;
import com.alawn.security.service.ResourceService;
import com.alawn.system.service.DictionaryService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

@Controller("/views/security/resource.faces")
@Join(path = "/security/resource", to = "/views/security/resource.faces")
public class ResourceController extends FacesController {

    @Autowired
    private ResourceService resourceService;

    @Autowired
    private DictionaryService dictionaryService;

    @Override
    public void initPage() {
        dataList(null);
        putViewScope("types", ResourceType.values());
    }

    public void dataList(Resource selected) {
        putViewScope("resources", resourceService.treeDataModel(selected));
        putViewScope("selectedNode", new DefaultTreeNode());

    }

    public void add() {
        Resource resource = new Resource();
        putViewScope("parents", resourceService.treeDataModel(ResourceType.BUTTON));
        putViewScope("resource", resource);
        putViewScope("selectedNode", new DefaultTreeNode(null));
        putViewScope("buttons", generateButtons());
    }

    public void edit() {
        Resource resource = (Resource) ((TreeNode) getViewScope("selectedNode")).getData();
        Resource parent = null;
        List<Resource> buttons = new ArrayList<>();
        if (resource != null && resource.getParentId() != null) {
            parent = resourceService.getById(resource.getParentId());
            if (ResourceType.PAGE.equals(resource.getType())) {
                buttons = resourceService
                        .list(new QueryWrapper<Resource>().lambda().eq(Resource::getParentId, resource.getId()));
            }
        }
        putViewScope("buttons", buttons.size() == 0 ? generateButtons() : buttons);
        putViewScope("parents", resourceService.treeDataModel(parent, ResourceType.BUTTON));
        putViewScope("selectedNode", new DefaultTreeNode(parent));
        putViewScope("resource", resource);
    }

    @SuppressWarnings("unchecked")
    @MessageRequired(type = MessageType.SAVE)
    public void save() {
        Resource resource = (Resource) getViewScope("resource");
        resourceService.saveOrUpdate(resource);
        List<Resource> buttons = (List<Resource>) getViewScope("buttons");
        if (ResourceType.PAGE.equals(resource.getType())) {
            buttons.forEach(button -> {
                button.setParentId(resource.getId());
                button.setPermission((resource.getCode() + ":" + button.getCode()).toLowerCase());
            });
            resourceService.saveOrUpdateBatch(buttons);
        }
        dataList(resource);
    }

    @MessageRequired(type = MessageType.DELETE)
    public void delete() {
        Resource resource = (Resource) ((TreeNode) getViewScope("selectedNode")).getData();
        resourceService.remove(new QueryWrapper<Resource>().lambda().or().eq(Resource::getId, resource.getId()).or()
                .eq(Resource::getParentId, resource.getId()));
        dataList(null);
    }

    public void onSelectParent(NodeSelectEvent event) {
        Resource resource = (Resource) getViewScope("resource");
        Long parentId = ((Resource) event.getTreeNode().getData()).getId();
        resource.setParentId(parentId);
        putViewScope("selectedNode", event.getTreeNode());
    }

    public void onChangeType(AjaxBehaviorEvent event) {
        SelectOneButton button = (SelectOneButton) event.getSource();
        Resource resource = (Resource) getViewScope("resource");
        resource.setType((ResourceType) button.getValue());
    }

    private List<Resource> generateButtons() {
        List<Dictionary> dictionaries = dictionaryService.findByClassify("BUTTON");
        return resourceService.createButtons(dictionaries);
    }
}
